Cloud Functions
Release Notes  |  Cloud Functions のドキュメント  |  Google Cloud
Cloud Functions の保護
Cloud Functions にサービスアカウントキーを渡す
Pub/Sub の HTTP Push 先を Cloud Functions にする
Cloud Functions から Stackdriver に log 書く & ログのグループ化(未完)
トリガ
イベントとトリガー  |  Cloud Functions のドキュメント  |  Google Cloud
実行モデル
Cloud Functions 実行環境  |  Google Cloud Functions に関するドキュメント
再利用される条件や timeout 時の挙動など
時刻
TZ 環境変数を設定したら日本時間になる
デプロイ時に --set-env-vars TZ=Asia/Tokyo など、Node & Go Runtime で確認
https://us-central1-pokutuna-dev.cloudfunctions.net/now-tz-default
https://us-central1-pokutuna-dev.cloudfunctions.net/now-tz-jst
https://us-central1-pokutuna-dev.cloudfunctions.net/nowgo-tz-default
https://us-central1-pokutuna-dev.cloudfunctions.net/nowgo-tz-jst
プロジェクト名は firebase と共通
プロジェクト名は共通の名前空間にある、firebase と gcp 一方で取ったプロジェクト名は共通して使えない
$ gcloud --project {project} functions deploy ... で firebase function 下にデプロイされる
これで Go で書いた function も firebase 下にデプロイできる、firebase hosting で叩けるかは未確認(たぶんいけるだろ)
Go で書く時
golang-samples/functions at master · GoogleCloudPlatform/golang-samples みる
http トリガなら type HandlerFunc func(ResponseWriter, *Request) を公開する
そうでない場合(PubSub, CloudStroage) func(ctx context.Context, e イベント) error の interface
code:event.go
type GCSEvent struct {
Bucket string json:"bucket"
Name string json:"name"
}
type PubSubMessage struct {
Data []byte json:"data"
}
単に kick するだけなら e interface{} で受け取って捨ててもよい
global は使い回されることもあるし
Tips & Tricks  |  Cloud Functions Documentation  |  Google Cloud
ヒントとアドバイス  |  Firebase
Cloud Function の状態は、将来の呼び出しのために必ずしも保持されるわけではありません。しかし、Cloud Functions が以前の呼び出しの実行環境をリサイクルすることはよくあります。変数をグローバル スコープで宣言すると、その値は再計算せずに後続の呼び出しで再利用できるようになります。
https://us-central1-pokutuna-dev.cloudfunctions.net/global_value
global の変数を increment して返してる例、コールドスタートなら 0 からになるはず
Promise を返す
If a Node.js background function returns a Promise, Cloud Functions ensures that the Promise is settled before terminating.
あとでやってみる
background function とは pubsub や Cloud Storage イベントによって起動されるやつ
http functions は別に promise を待たない
--entry-point など function 設定として記憶されるオプション
--region など初回デプロイ時に渡すと以降省略しても同じリージョンにデプロイされるように
一度 --entry-point=app としてデプロイすると app が export されることを期待するようになる
その後 app を export しない実装をデプロイするとエラーになる
Deploying function (may take a while - up to 2 minutes)...
..............................................................................................................................................failed.
ERROR: (gcloud.functions.deploy) OperationError: code=13, message=Error setting up the execution environment for your function. Please try deploying again after a few minutes.
middleware
Express.js 入れなくてもミドルウェア単体でもいいじゃん
export.app = middeware(req, res, () => { ... })
req.rawBody がある
HTTP 関数  |  Cloud Functions のドキュメント  |  Google Cloud
rawBody プロパティには、リクエスト本文の未解析バイト数が組み込まれています。
ふつう express.json() ミドルウェアを有効にしたらその後のハンドラでは req.body がパースされた状態になる
生のリクエストボディとパースした body 両方にアクセスしたい場合ひと手間ある Express.js#5dee6dc0384461000063961b
アプリケーションの外でやってくれているのはありがたい(なぜか rawBody が入ってて正しく動いた)
@google-cloud/functions-framework でも入っている
https://github.com/GoogleCloudPlatform/functions-framework-nodejs/blob/0b348e8e643c5d7212e6a4812f203ba3812ff159/src/invoker.ts#L302L316
環境変数
Using Environment Variables  |  Cloud Functions Documentation  |  Google Cloud
table:env
GCP_PROJECT Reserved: The current GCP project ID.
FUNCTION_NAME Reserved: The name of the function resource.
FUNCTION_TIMEOUT_SEC Reserved: The execution timeout in seconds.
FUNCTION_IDENTITY Reserved: The current identity (service account) of the function.
FUNCTION_REGION Reserved: The function region (example: us-central1).
使いそうなのはこのあたりかな?
function から外部アクセスする際の timeout も適当にセットするのでなく、FUNCTION_TIMEOUT_SEC から伸縮できると印象が良いですね
nodejs10 runtime で値が全然足りてない、process.env を出力した例
code:process.env
"NO_UPDATE_NOTIFIER":"true",
"FUNCTION_TARGET":"logWithBunyan",
"NODE_OPTIONS":"--max-old-space-size=256",
"NODE_ENV":"production",
"PWD":"/srv/functions",
"HOME":"/root",
"DEBIAN_FRONTEND":"noninteractive",
"PORT":"8080",
"K_REVISION":"6",
"K_SERVICE":"logWithBunyan",
"SHLVL":"1",
"FUNCTION_SIGNATURE_TYPE":"http",
"PATH":"/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
"OLDPWD":"/srv",
"_":"../start-functions-framework"d
@google-cloud/logging でも K_SERVICE 見たりしている
nodejs-logging/metadata.ts at 857edb6098050d919927ca3cedd54bd22447565b · googleapis/nodejs-logging
(これでも nodejs10 では region 取れてない)
node8js & nodejs10 runtime の環境変数やリクエストヘッダ
https://us-central1-pokutuna-dev.cloudfunctions.net/envs-node8
https://us-central1-pokutuna-dev.cloudfunctions.net/envs-node10
app.enable('trust proxy') 済み
req.ip は X-Forwarded-For の左を返す
https://github.com/GoogleCloudPlatform/functions-framework-nodejs/blob/0b348e8e643c5d7212e6a4812f203ba3812ff159/src/invoker.ts#L574
例外が出たときの状態
node10 では module が再読み込みされリセットされる
https://github.com/pokutuna/cloud-functions-playground/tree/master/state-and-error
リクエストするたびカウントアップ
?throw=1 で例外投げる
カウントがゼロに戻る
コールドスタートから
クラッシュすると再利用されない
Cloud Functions 実行環境  |  Google Cloud Functions に関するドキュメント
"正しく" エラーを返す(HTTP 関数で 500 をレスポンスする)場合は再利用されうる
Provided code is not a loadable module.
Provided code is not a loadable module.
Could not load the function, shutting down.
なにが悪いのか情報が足りないエラー、コンソールから zip でアップロードしたファイルをダウンロードできるので、落としてきてデバッグする
僕がこれを見る場合、1回目はデプロイできたのに2回目は失敗する! とハマっている
初回のデプロイでは .gcloudignore を置いてなくて作られる
#!include:.gitignore が含まれており、.gitignore しているファイルはアップロードしなくなる
その後に TypeScript プロジェクトなので、build/ 以下 ignore し忘れてたわ、と .gitignore に追加する
2回目のデプロイであれさっきできてたのにできねーぞ!!
となる
#GoogleCloud